# Reksio - Memory Map Editor
# Copyright (C) 2023 CERN
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
#
# In applying this licence, CERN does not waive the privileges and immunities
# granted to it by virtue of its status as an Intergovernmental Organization or
# submit itself to any jurisdiction.

try:
    import reksio
except ImportError:
    # running without the GUI
    class reksio:
        warn = print
        info = print

import fileutils
import upgrades

from pathlib import Path
from tree import TreeView
from upgrades import UPGRADES
from shutil import copy2
from tools_runner import Settings, HDLGenerator


def before_load(filename):
    # reksio.info(f"Before load script {filename}")
    # do nothing - return original filename

    f_path = Path(filename)

    if not f_path.exists():
        # let the GUI handle this
        return filename

    # get the extension
    extension = f_path.suffix

    if extension == ".xml":
        return handle_xml(filename)
    elif extension in ['.cheby', '.yaml']:
        return handle_yaml(filename)
    elif extension == ".wb":
        return handle_wb(filename)

    # not handled, return original one
    return filename


def handle_wb(filename):
    main_window = reksio.get_main_window()

    box = reksio.QMessageBox(main_window)
    box.setText(f"You're trying to open a WB memory-map, which needs conversion. "
                f"Would you like to proceed and convert the file? "
                f"It will be saved next to .wb file, but with .cheby extension. "
                f"Warning!"
                f"Existing .cheby files will be replaced!")
    box.setIcon(reksio.QMessageBox.Icon.Question)
    yes_btn = box.addButton(reksio.QMessageBox.StandardButton.Yes)
    box.addButton(reksio.QMessageBox.StandardButton.Cancel)

    box.exec()

    clicked_btn = box.clickedButton()

    if clicked_btn == yes_btn:
        import cheby.wbgen2cheby as wbgen2cheby
        new_filename = str(Path(filename).with_suffix('.cheby'))
        with open(new_filename, 'w') as f:
            wbgen2cheby.convert(f, filename)
        create_wb_gen_settings(new_filename)
        return new_filename
    else:
        return filename


def handle_xml(filename):
    main_window = reksio.get_main_window()

    box = reksio.QMessageBox(main_window)
    box.setText(f"You're trying to open an XML memory-map, which needs conversion. "
                f"Would you like to proceed and convert files? "
                f"They will be saved next to .xml files, but with .cheby extension. "
                f"Warning!"
                f"Existing .cheby files will be replaced!")
    box.setIcon(reksio.QMessageBox.Icon.Question)
    yes_btn = box.addButton(reksio.QMessageBox.StandardButton.Yes)
    box.addButton(reksio.QMessageBox.StandardButton.Cancel)

    box.exec()

    clicked_btn = box.clickedButton()
    if clicked_btn == yes_btn:
        return fileutils.convert_xml_to_cheby(filename)

    return filename


def create_wb_gen_settings(main_file):
    settings_file = HDLGenerator.get_settings_file(main_file)
    settings = Settings(settings_file, HDLGenerator.CONFIG_PATH, HDLGenerator.get_arguments(), save=False)
    settings['generator'] = 'wb'
    settings.save()


def create_gena_gen_settings(main_file):
    try:
        # load the file
        data = fileutils.load_yaml_file(main_file)

        root_node = TreeView(data, 'memory-map')
        root_node.filename = main_file

        submaps = fileutils.get_submaps(root_node)

        all_maps = submaps + [root_node]

        for mem_map in all_maps:
            mem_map_file = mem_map.filename
            settings_file = HDLGenerator.get_settings_file(mem_map_file)
            settings = Settings(settings_file, HDLGenerator.CONFIG_PATH, HDLGenerator.get_arguments(), save=False)
            settings['generator'] = 'gena'
            settings.save()
    except Exception as e:
        reksio.warn(f"Exception while processing yaml to create gena settings files: {e}")


def handle_yaml(filename, quiet=False):
    try:
        # load the file
        data = fileutils.load_yaml_file(filename)

        root_node = TreeView(yaml_tree=data, root_node='memory-map', global_root=True)
        root_node.filename = filename

        submaps = fileutils.get_submaps(root_node)

        all_maps = submaps + [root_node]

        user_informed_about_upgrade = False or quiet

        for memory_map in all_maps:
            if upgrades.is_update_needed(memory_map):

                if not user_informed_about_upgrade:
                    main_window = reksio.get_main_window()

                    box = reksio.QMessageBox(main_window)
                    box.setText(f"You're trying to open older version of a memory-map, which needs an upgrade. "
                                f"Would you like to proceed and upgrade files? "
                                f"Existing files will be replaced and backup files will be created with .bak extension.")
                    box.setIcon(reksio.QMessageBox.Icon.Question)
                    yes_btn = box.addButton(reksio.QMessageBox.StandardButton.Yes)
                    box.addButton(reksio.QMessageBox.StandardButton.Cancel)

                    box.exec()

                    clicked_btn = box.clickedButton()

                    if clicked_btn != yes_btn:
                        filename = ""  # no file, cancelled, will be returned at the end
                        reksio.warn(f"Memory map upgrade cancelled.")
                        break
                    user_informed_about_upgrade = True

                reksio.warn(f"Memory map {str(memory_map.filename)} will be updated.\n"
                                     f"A backup will be created with .bak extension.")
                fileutils.backup(memory_map)
                upgrades.upgrade(memory_map)
                reksio.info(f"Update of {str(memory_map.filename)} succeeded.")
                fileutils.save(memory_map)
    except Exception as e:
        reksio.warn(f"Exception while processing yaml: {e}, file: {filename}")
    finally:
        return filename


if __name__ == "__main__":
    # running without the GUI
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("-f", "--file", help="Parse single file (and submaps)")
    parser.add_argument("-d", "--dir", help="Scan whole directory and update all .cheby files")
    args = parser.parse_args()

    if args.file:
        handle_yaml(args.file, quiet=True)
    elif args.dir:
        import glob
        map_files = glob.glob(args.dir + "/**/*.cheby", recursive=True)
        for map_file in map_files:
            handle_yaml(map_file, quiet=True)

